package web.eshop.wizard;


import domain.shop.Product;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.PageParameters;
import org.apache.wicket.ResourceReference;
import org.apache.wicket.extensions.wizard.WizardStep;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import service.ImageService;
import service.facade.customer.ShopCustomerService;
import web.eshop.SimpleProductEshopPage;

import java.io.Serializable;
import java.util.*;
import java.util.logging.Logger;

/**
 * In this step customer choose which compoments and how many want to add into order.
 */
public final class RegWizardThirdStep extends WizardStep {
    private static Logger logger = Logger.getLogger(RegWizardThirdStep.class.getName());

    @SpringBean
    private ShopCustomerService shopCustomerService;
    @SpringBean
    private ImageService imageService;
    private InputForm inputForm;
    private final Label noComponentsFoundLabel;

    public RegWizardThirdStep(RegWizardModel regWizardModel) {
        inputForm = new InputForm("inputForm", regWizardModel);
        add(inputForm);
        noComponentsFoundLabel = new Label("noComponentsFoundLabel", "Vybraný produkt nemá žádné komponenty");
        noComponentsFoundLabel.setVisible(false);
        add(noComponentsFoundLabel);
    }

    public ThirdStepResultSet getThirdStepResultSet() {
        return inputForm.getThirdStepResultSet();
    }

    public class ThirdStepResultSet {

        private Map<Long, Integer> multiplicityMap;
        private List<Long> selectedProductsIds;

        public ThirdStepResultSet(Map<Long, Integer> multiplicityMap, List<Long> selectedProductsIds) {
            this.multiplicityMap = multiplicityMap;
            this.selectedProductsIds = selectedProductsIds;
        }

        public Map<Long, Integer> getMultiplicityMap() {
            return multiplicityMap;
        }

        public List<Long> getSelectedProductsIds() {
            return selectedProductsIds;
        }
    }

    /**
     * form for processing the input.
     */
    private class InputForm extends Form {

        private RegWizardModel regWizardModel;
        private LoadableDetachableModel<List<ProductWrapper>> localModel;

        public ThirdStepResultSet getThirdStepResultSet() {
            Map<Long, Integer> multiplicityMap = new HashMap<Long, Integer>();
            List<ProductWrapper> wrappedProducts = localModel.getObject();
            List<Long> selectedComponentsIds = new ArrayList<Long>();
            for (ProductWrapper productWrapper : wrappedProducts) {
                if (productWrapper.getSelected()) {
                    selectedComponentsIds.add(productWrapper.getProductId());
                    multiplicityMap.put(productWrapper.getProductId(), productWrapper.getMultiplicity());
                }
            }
            return new ThirdStepResultSet(multiplicityMap, selectedComponentsIds);
        }

        private InputForm(String id, RegWizardModel model) {
            super(id);
            this.regWizardModel = model;
            localModel = new LoadableDetachableModel<List<ProductWrapper>>() {

                @Override
                protected List<ProductWrapper> load() {
                    Product selectedProduct = shopCustomerService.findProductById(
                            regWizardModel.getSelectedProductId());

                    Set<Product> products = selectedProduct.getComponents();
                    List<ProductWrapper> productWrappers = new ArrayList<ProductWrapper>(products.size());

                    if (products.size() == 0) {
                        noComponentsFoundLabel.setVisible(true);
                    } else {
                        noComponentsFoundLabel.setVisible(false);
                    }

                    for (Product product : products) {
                        ProductWrapper pWrapper = new ProductWrapper(product);
                        productWrappers.add(pWrapper);
                    }
                    return productWrappers;
                }
            };

            // add a nested list view; as the list is nested in the form, the form will
            // update all FormComponent childs automatically.
            add(new ListView<ProductWrapper>("productsList", localModel) {

                {
                    this.setReuseItems(true);
                }

                protected void populateItem(ListItem<ProductWrapper> item) {
                    final Long productId = item.getModelObject().getProductId();

                    item.add(new CheckBox("productsSelected",
                            new PropertyModel(item, "modelObject.selected")));

                    item.add(new TextField<Integer>("multiplicity",
                            new PropertyModel<Integer>(item, "modelObject.multiplicity")));

                    Link link = new Link("link") {

                        @Override
                        public void onClick() {
                            Map<String, Long> paramsMap = new HashMap<String, Long>();
                            paramsMap.put("0", productId);
                            setResponsePage(SimpleProductEshopPage.class, new PageParameters(paramsMap));
                        }
                    };

                    link.add(new Label("name", new PropertyModel(item, "modelObject.product.name")));
                    item.add(link);

                    //Image
                    boolean available = false;
                    try {
                        available =
                                imageService.isImageAvailable(item.getModelObject().getProduct().
                                        getMainImage());
                    } catch (Exception e) {
                        logger.severe("Produkt nema prirazeny obrazek");
                    }


                    Link imgLink = new Link("imgLink") {

                        @Override
                        public void onClick() {
                            Map<String, Long> paramsMap = new HashMap<String, Long>();
                            paramsMap.put("0", productId);
                            setResponsePage(SimpleProductEshopPage.class, new PageParameters(paramsMap));
                        }
                    };


                    ResourceReference ref = new ResourceReference("imageResource");
                    Long id = null;
                    try {
                        id = item.getModelObject().getProduct().getMainImage().getId();
                    } catch (Exception e) {
                        logger.severe("null in RegWizardThirdStep.java");
                    }


                    String url = getRequestCycle().urlFor(ref) + "/imageEntryId/" + id;
                    //String url = "/Product/" + productId;
                    url = url + "/thumbnail/true";
                    AttributeModifier modifier = new AttributeModifier(
                            "src",
                            new Model(url));

                    /*Map<String, Long> paramsMap = new HashMap<String, Long>();
                    paramsMap.put("0", productId);
                    setResponsePage(SimpleProductEshopPage.class, new PageParameters(paramsMap));*/

                    //ExternalLink imgLink = new ExternalLink("imgLink", url);

                    Label label = new Label("thumbnailImage", "");
                    label.add(modifier);
                    label.setVisible(available);
                    imgLink.add(label);

                    label = new Label("thumbnailImageNA", "");
                    label.add(modifier);
                    label.setVisible(!available);
                    imgLink.add(label);

                    item.add(imgLink);

                }
            });
        }
    }

    private class ProductWrapper implements Serializable {

        private Long productId;
        private Boolean selected = Boolean.FALSE;
        private transient Product product;
        private Integer multiplicity = 1;

        public ProductWrapper(Product product) {
            this.productId = product.getId();
        }

        public Integer getMultiplicity() {
            return multiplicity;
        }

        public void setMultiplicity(Integer multiplicity) {
            this.multiplicity = multiplicity;
        }

        public Boolean getSelected() {
            return selected;
        }

        public void setSelected(Boolean selected) {
            this.selected = selected;
        }

        public Long getProductId() {
            return productId;
        }

        public Product getProduct() {
            if (product == null) {
                return product = shopCustomerService.findProductById(productId);
            }
            return product;
        }
    }
}
